package com.ym.producer.util;

import lombok.Builder;
import lombok.Data;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;

public class DateUtil {
    public static Timestamp stringToTimestamp(String time) {
        return new Timestamp(DateUtil.stringToDate(time).getTime());
    }

    public static String timestampToString(Timestamp time, String format) {
        String timeStr = "";
        DateFormat sdf = new SimpleDateFormat(format);
        try {
            //方法一
            timeStr = sdf.format(time);

            //方法二
//            timeStr = time.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return timeStr;
    }

    public static Timestamp dateToTimestamp(Date time) {
        return new Timestamp(time.getTime());
    }

    public static Date timestampToDate(Timestamp time) {
        return time;
    }

    public static String dateToString(){
        return dateToString(new Date(),getFormatter(19));
    }
    public static String dateToString(Date time, String format) {
        String timeStr = "";
        //format的格式可以任意
        DateFormat sdf = new SimpleDateFormat(format);
        try {
            timeStr = sdf.format(time);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return timeStr;
    }
    public static Date stringToDate(String time,String formatter)  {
        DateFormat sdf = new SimpleDateFormat(formatter);
        try {
            return sdf.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return new Date();
    }
    public static Date stringToDate(String time) {
        String formatter = DateUtil.getFormatter(time.length());

        Date date = new Date();
        //注意format的格式要与日期String的格式相匹配
        DateFormat sdf = new SimpleDateFormat(formatter);
        try {
            date = sdf.parse(time);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 获取某一年的第一天
     * @param year
     * @return
     */
    public static Date getYearFirst(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        return calendar.getTime();
    }
    /**
     * 获取某一年的第一天
     * @param year
     * @return
     */
    public static Date getYearFirst(String year) {
        return getYearFirst(Integer.parseInt(year));
    }

    /**
     * 获取某一年最后一天
     * @param year
     * @return
     */
    public static Date getYearLast(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        Date currYearLast = calendar.getTime();

        return currYearLast;
    }
    /**
     * 获取某一年最后一天的最后一秒
     * @param year
     * @return
     */
    public static Date getYearSecondLast(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        return calendar.getTime();
    }
    /**
     * 获取某一年最后一天的最后一秒
     * @param year
     * @return
     */
    public static Date getYearSecondLast(String year) {
        return getYearSecondLast(Integer.parseInt(year));
    }

    /**
     * 获取某一月的第一天
     * @param year
     * @param month
     * @return
     */
    public static Date getMonthFirst(int year,int month){
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH,month-1);
        return calendar.getTime();
    }
    /**
     * 获取某月第一天
     * @param monthDate 格式 yyyy-mm; yyyy/mm
     * @return
     */
    public static Date getMonthFirst(String monthDate) {
        String[] strs = monthDate.split("[-|/]");
        return getMonthFirst(Integer.parseInt(strs[0]),Integer.parseInt(strs[1]));
    }
    /**
     * 获取某月最后一天
     * @param monthDate 格式 yyyy-mm; yyyy/mm
     * @return
     */
    public static Date getMonthLast(String monthDate) {
        String[] strs = monthDate.split("[-|/]");
        return getMonthLast(Integer.parseInt(strs[0]),Integer.parseInt(strs[1]));
    }
    /**
     * 获取某一月的最后一天
     * @param year
     * @param month
     * @return
     */
    public static Date getMonthLast(int year,int month){
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH,month);
        calendar.set(Calendar.DAY_OF_MONTH,0);

        return calendar.getTime();
    }

    /**
     * 获取某一月的最后一天的最后一秒
     * @param year
     * @param month
     * @return
     */
    public static Date getMonthSecondLast(int year,int month){
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH,month);
        calendar.set(Calendar.DAY_OF_MONTH,0);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        return calendar.getTime();
    }
    /**
     * 获取某一月的最后一天的最后一秒
     * @param monthDate 格式 yyyy-mm; yyyy/mm
     * @return
     */
    public static Date getMonthSecondLast(String monthDate){
        String[] strs = monthDate.split("[-|/]");
        return getMonthSecondLast(Integer.parseInt(strs[0]),Integer.parseInt(strs[1]));
    }

    public static void main(String[] args) {
        System.out.println(DateUtil.dateToString(DateUtil.getMonthFirst("2020/12"),DateUtil.getFormatter(19)));
    }


    public static String getFormatter(int length) {
        String formatter = "yyyy-MM-dd";
        if (length == 16) {
            formatter = "yyyy-MM-dd HH:mm";
        } else if (length == 19) {
            formatter = "yyyy-MM-dd HH:mm:ss";
        } else if (length == 20) {
            formatter = "yyyy-MM-dd HH:mm:ss.S";
        } else if (length == 21) {
            formatter = "yyyy-MM-dd HH:mm:ss.SS";
        } else if (length == 22) {
            formatter = "yyyy-MM-dd HH:mm:ss.SSS";
        } else if (length == 5){
            formatter = "HH:mm";
        }
        return formatter;
    }


    // 计算指定时间的之前或之后多久时间(获取目标时间-值代表之前，+值代表之后)
    public static Date getTargetDate(Date nodeDate, int years, int months, int days, int hours, int minutes, int seconds) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(nodeDate);
        calendar.add(Calendar.SECOND, seconds);
        calendar.add(Calendar.MINUTE, minutes);
        calendar.add(Calendar.HOUR, hours);
        calendar.add(Calendar.DATE, days);
        calendar.add(Calendar.MONTH, months);
        calendar.add(Calendar.YEAR, years);

        return calendar.getTime();
    }

    // 计算指定时间的之前或之后多久时间(获取目标时间-值代表之前，+值代表之后)
    public static Date increasedSeconds(Date nodeDate,int seconds) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(nodeDate);
        calendar.add(Calendar.SECOND, seconds);
        return calendar.getTime();
    }

    public static String getFormatDate() {
        return new java.sql.Date(System.currentTimeMillis()).toString().replace("-", "");
    }

    /**
     * 获取 2 个时间的自然年历的时间间隔
     *
     * @param inDate     入院时间，需要大于 出生日期
     * @param birthDay   出生日期
     * @return [年, 月, 日, 小时, 分钟, 秒]的数组
     */
    public static int[] getTimeIntervalArray(Date inDate, Date birthDay) {
        Calendar nextDate = Calendar.getInstance();
        Calendar previousDate = Calendar.getInstance();
        nextDate.setTime(inDate);
        previousDate.setTime(birthDay);
        int year = nextDate.get(Calendar.YEAR) - previousDate.get(Calendar.YEAR);
        int month = nextDate.get(Calendar.MONTH) - previousDate.get(Calendar.MONTH);
        int day = nextDate.get(Calendar.DAY_OF_MONTH) - previousDate.get(Calendar.DAY_OF_MONTH);
        int hour = nextDate.get(Calendar.HOUR_OF_DAY) - previousDate.get(Calendar.HOUR_OF_DAY);// 24小时制
        int min = nextDate.get(Calendar.MINUTE) - previousDate.get(Calendar.MINUTE);
        int second = nextDate.get(Calendar.SECOND) - previousDate.get(Calendar.SECOND);

        boolean hasBorrowDay = false;// "时"是否向"天"借过一位

        if (second < 0) {
            second += 60;
            min--;
        }

        if (min < 0) {
            min += 60;
            hour--;
        }

        if (hour < 0) {
            hour += 24;
            day--;

            hasBorrowDay = true;
        }

        if (day < 0) {
            // 计算截止日期的上一个月有多少天，补上去
            Calendar tempDate = (Calendar) nextDate.clone();
            tempDate.add(Calendar.MONTH, -1);// 获取截止日期的上一个月
            day += tempDate.getActualMaximum(Calendar.DAY_OF_MONTH);

            // nextDate是月底最后一天，且day=这个月的天数，即是刚好一整个月，比如20160131~20160229，day=29，实则为1个月
            if (!hasBorrowDay
                    && nextDate.get(Calendar.DAY_OF_MONTH) == nextDate.getActualMaximum(Calendar.DAY_OF_MONTH)// 日期为月底最后一天
                    && day >= nextDate.getActualMaximum(Calendar.DAY_OF_MONTH)) {// day刚好是nextDate一个月的天数，或大于nextDate月的天数（比如2月可能只有28天）
                day = 0;// 因为这样判断是相当于刚好是整月了，那么不用向 month 借位，只需将 day 置 0
            } else {// 向month借一位
                month--;
            }
        }

        if (month < 0) {
            month += 12;
            year--;
        }

        return new int[]{year, month, day, hour, min, second};
    }

    /**
     * 年月日时分数组根据年龄格式置空
     * @param timeIntervalArray
     * @return
     */
    public static Integer[] getAgeTimeIntervalArray(int[] timeIntervalArray) {
        Integer ageYear = timeIntervalArray[0];
        Integer ageMonth = timeIntervalArray[1];
        Integer ageDay = timeIntervalArray[2];
        Integer ageHour = timeIntervalArray[3];
        Integer ageMinute = timeIntervalArray[4];
        if (ageYear >= 3) {        //3岁以上            X岁
            ageMonth = null;
            ageDay = null;
            ageHour = null;
            ageMinute = null;
        } else if (ageYear >= 1) {     //1岁以上        X岁X月
            ageDay = null;
            ageHour = null;
            ageMinute = null;
        } else if (ageMonth >= 1) {        //1月以上    X月X天
            ageYear = null;
            ageHour = null;
            ageMinute = null;
        } else if (ageDay >= 1) {          //1天以上     X天X小时
            ageYear = null;
            ageMonth = null;
            if (ageDay > 28) {              //28天以上不需要小时
                ageHour = null;
            }
            ageMinute = null;
        } else {                //1天以下           X小时X分钟
            ageYear = null;
            ageMonth = null;
            ageDay = null;
        }
        return new Integer[]{ageYear, ageMonth, ageDay, ageHour, ageMinute};
    }

    /**
     * LocalDateTime转换为Date
     * @param localDateTime
     */
    public static Date localDateTime2Date( LocalDateTime localDateTime){
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

    /**
     * 得到几天后的时间
     * @param date
     * @param day
     * @return
     */
    public static Date getDateAfter(Date date,int day){
        Calendar now =Calendar.getInstance();
        now.setTime(date);
        now.set(Calendar.DATE,now.get(Calendar.DATE)+day);
        return now.getTime();
    }

    public static LocalDateTime StringToLocalDateTime(String executeBeginTime, String formatter) {


        return dateToLocalDateTime(stringToDate(executeBeginTime,formatter));
    }

    public  static LocalDateTime dateToLocalDateTime(Date date){
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();

        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        return localDateTime;
    }

    public static String dateStringForamtter(String date) {
        Date dateTime = stringToDate(date);
        return dateToString(dateTime,getFormatter(19));
    }


    public static int getDayDiffer(Date startDate, Date endDate) throws ParseException {
        //判断是否跨年
        SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy");
        String startYear = yearFormat.format(startDate);
        String endYear = yearFormat.format(endDate);
        if (startYear.equals(endYear)) {
            /*  使用Calendar跨年的情况会出现问题    */
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startDate);
            int startDay = calendar.get(Calendar.DAY_OF_YEAR);
            calendar.setTime(endDate);
            int endDay = calendar.get(Calendar.DAY_OF_YEAR);
            return endDay - startDay;
        } else {
            /*  跨年不会出现问题，需要注意不满24小时情况（2016-03-18 11:59:59 和 2016-03-19 00:00:01的话差值为 0）  */
            //  只格式化日期，消除不满24小时影响
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            long startDateTime = dateFormat.parse(dateFormat.format(startDate)).getTime();
            long endDateTime = dateFormat.parse(dateFormat.format(endDate)).getTime();
            return (int) ((endDateTime - startDateTime) / (1000 * 3600 * 24));
        }
    }
    /**
     *  处理时间
     * @param date  原时间
     * @param expireMiute  增加时间(分钟)
     * @return
     * @throws ParseException
     */
    public static Date addMinutes(Date date, int expireMiute) {
        Date expireTime = new Date(date.getTime() + expireMiute * 60 * 1000);
        return expireTime;
    }
    /**
     * 计算2个日期之间相差的  以年、月、日为单位，各自计算结果是多少
     * 比如：2011-02-02 到  2017-03-02
     *                                以年为单位相差为：6年
     *                                以月为单位相差为：73个月
     *                                以日为单位相差为：2220天
     * @param fromDate
     * @param toDate
     * @return
     */
    public static DayCompare dayCompare(Date fromDate,Date toDate){
        Calendar  from  =  Calendar.getInstance();
        from.setTime(fromDate);
        Calendar  to  =  Calendar.getInstance();
        to.setTime(toDate);
        //只要年月
        int fromYear = from.get(Calendar.YEAR);
        int fromMonth = from.get(Calendar.MONTH);
        int toYear = to.get(Calendar.YEAR);
        int toMonth = to.get(Calendar.MONTH);
        int year = toYear  -  fromYear;
        int month = toYear *  12  + toMonth  -  (fromYear  *  12  +  fromMonth);
        int day = (int) ((to.getTimeInMillis()  -  from.getTimeInMillis())  /  (24  *  3600  *  1000));
        return DayCompare.builder().day(day).month(month).year(year).build();
    }
    @Data
    @Builder
    public static class DayCompare{
        private int year;
        private int month;
        private int day;
    }

    /**
     * 得到几天前的时间
     * @param date
     * @param day
     * @return
     */
    public static Date getDateBefore(Date date,int day){
        Calendar now =Calendar.getInstance();
        now.setTime(date);
        now.set(Calendar.DATE,now.get(Calendar.DATE)-day);
        return now.getTime();
    }
}
